import numpy as np
import math
from sklearn import svm
from sklearn.metrics import accuracy_score
from sklearn import naive_bayes
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier
from sklearn import tree
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import GradientBoostingClassifier
import joblib
'''
path = 'C:/Users/Administrator/Desktop/Real-Time-Action-Recognition-master/date.txt'

data = np.loadtxt(path, dtype=int, delimiter=',', encoding='utf-8')
data.tolist()
'''
data = np.array([[306, 64,306,127,259,127,259,178,282,127,353,127,388,191,  0,  0,282,305, 270,420,259,521,353,318,341,
                  420,353,521,294, 64,318, 64,282, 64,329, 64]])
coulum = data.shape[0]#行数
#y_data = np.array(data[::, -1])#转化标签为矩阵形式
'''
#def K_linear_function():
k1_0 = (data[0][3] - data[0][1]) / (data[0][2] - data[0][0])
k1_2 = (data[0][3] - data[0][5]) / (data[0][2] - data[0][4])
k2_3 = (data[0][5] - data[0][7]) / (data[0][4] - data[0][6])
k3_4 = (data[0][7] - data[0][9]) / (data[0][6] - data[0][8])
k1_5 = (data[0][3] - data[0][11]) / (data[0][2] - data[0][10])
k5_6 = (data[0][11] - data[0][13]) / (data[0][10] - data[0][12])
k6_7 = (data[0][13] - data[0][15]) / (data[0][12] - data[0][14])
#如果腿部点缺失,那就依次从大腿,膝盖,脚踝,进行计算k值
#右腿
k1_8 = (data[0][3] - data[0][17]) / (data[0][2] - data[0][16])
k1_9 = (data[0][3] - data[0][19]) / (data[0][2] - data[0][18])
k1_10 = (data[0][3] - data[0][21]) / (data[0][2] - data[0][20])
#左腿
k1_11 = (data[0][3] - data[0][23]) / (data[0][2] - data[0][22])
k1_12 = (data[0][3] - data[0][25]) / (data[0][2] - data[0][24])
k1_13 = (data[0][3] - data[0][27]) / (data[0][2] - data[0][26])
#左右眼
k0_14 = (data[0][1] - data[0][29]) / (data[0][0] - data[0][28])
k0_15 = (data[0][1] - data[0][33]) / (data[0][0] - data[0][32])  
#print(tan1, tan2, tan3, tan4, tan5, tan6)
'''
#计算得到两点之间直线方程的斜率
def joint_linear_k(data):
    K = []
    for i in range(coulum):
        K.append([])
        for j in range(1):
            k1_0 = (data[i][3] - data[i][1]) / (data[i][2] - data[i][0])
            K[i].append(k1_0)  # 0
            k1_2 = (data[i][3] - data[i][5]) / (data[i][2] - data[i][4])
            K[i].append(k1_2)  # 1
            k2_3 = (data[i][5] - data[i][7]) / (data[i][4] - data[i][6])
            K[i].append(k2_3)  # 2
            k3_4 = (data[i][7] - data[i][9]) / (data[i][6] - data[i][8])
            K[i].append(k3_4)  # 3
            k1_5 = (data[i][3] - data[i][11]) / (data[i][2] - data[i][10])
            K[i].append(k1_5)  # 4
            k5_6 = (data[i][11] - data[i][13]) / (data[i][10] - data[i][12])
            K[i].append(k5_6)  # 5
            k6_7 = (data[i][13] - data[i][15]) / (data[i][12] - data[i][14])
            K[i].append(k6_7)  # 6
            k1_8 = (data[i][3] - data[i][17]) / (data[i][2] - data[i][16])
            K[i].append(k1_8)  # 7
            k1_11 = (data[i][3] - data[i][23]) / (data[i][2] - data[i][22])
            K[i].append(k1_11)  # 8
            k0_14 = (data[i][1] - data[i][29]) / (data[i][0] - data[i][28])
            K[i].append(k0_14)  # 9
            k0_15 = (data[i][1] - data[i][33]) / (data[i][0] - data[i][32])
            K[i].append(k0_15)  # 10

    return K

#根据相交的两直线方程计算出夹角值
def get_joint_theta(K, data):
    theta = []
    for i in range(coulum):
        theta.append([])
        for j in range(1):
            # tan1 = ((k1_2 - k2_3) / (k1_2 * k2_3) + 1)
            tan1 = ((K[i][0] - K[i][1]) / (K[i][0] * K[i][1]) + 1)
            if K[i][1] == float('inf') or K[i][1] == float('-inf'):
                cos1 = ((data[i][5] * data[i][3] + data[i][4] * data[i][2]) / \
                       (math.sqrt(data[i][4] * data[i][4] + data[i][5] * data[i][5])
                         * math.sqrt(data[i][3] * data[i][3] + data[i][2] * data[i][2])))
                tan_1 = math.pi - math.acos(cos1)
                theta[i].append(tan_1)
            elif K[i][0] == float('inf') or K[i][0] == float('-inf'):
                cos2 = ((data[i][1] * data[i][3] + data[i][0] * data[i][2]) / \
                       (math.sqrt(data[i][0] * data[i][0] + data[i][1] * data[i][1])
                         * math.sqrt(data[i][2] * data[i][2] + data[i][3] * data[i][3])))
                tan_2 = math.pi - math.acos(cos2)
                theta[i].append(tan_2)
            else:
                theta[i].append(math.atan(tan1))
            # tan2 = ((k2_3 - k3_4) / (k3_4 * k2_3 + 1))
            tan2 = ((K[i][2] - K[i][3]) / (K[i][2] + K[i][3]) + 1)
            if K[i][2] == float('inf') or K[i][2] == float('-inf'):
                cos3 = ((data[i][5] * data[i][7] + data[i][4] * data[i][6]) / \
                       (math.sqrt(data[i][4] * data[i][4] + data[i][5] * data[i][5])
                         * math.sqrt(data[i][6] * data[i][6] + data[i][7] * data[i][7])))
                tan_3 = math.pi - math.acos(cos3)
                theta[i].append(tan_3)
            elif K[i][3] == float('inf') or K[i][3] == float('-inf'):
                cos4 = ((data[i][7] * data[i][9] + data[i][6] * data[i][8]) / \
                       (math.sqrt(data[i][6] * data[i][6] + data[i][7] * data[i][7])
                         * math.sqrt(data[i][8] * data[i][8] + data[i][9] * data[i][9])))
                tan_4 = math.pi - math.acos(cos4)
                theta[i].append(tan_4)
            else:
                theta[i].append(math.atan(tan2))
            # tan3 = ((k5_6 - k1_5) / (k5_6 * k1_5 + 1))
            tan3 = ((K[i][5] - K[i][4]) / (K[i][4] * K[i][5]) + 1)
            if K[i][5] == float('inf') or K[i][5] == float('-inf'):
                cos5 = ((data[i][11] * data[i][13] + data[i][10] * data[i][12]) / \
                       (math.sqrt(data[i][10] * data[i][10] + data[i][11] * data[i][11])
                         * math.sqrt(data[i][12] * data[i][12] + data[i][13] * data[i][13])))
                tan_5 = math.pi - math.acos(cos5)
                theta[i].append(tan_5)
            elif K[i][4] == float('inf') or K[i][4] == float('-inf'):
                cos4 = ((data[i][3] * data[i][11] + data[i][2] * data[i][10]) / \
                       (math.sqrt(data[i][3] * data[i][3] + data[i][2] * data[i][2])
                         * math.sqrt(data[i][10] * data[i][10] + data[i][11] * data[i][11])))
                tan_6 = math.pi - math.acos(cos4)
                theta[i].append(tan_6)
            else:
                theta[i].append(math.atan(tan3))
            # tan4 = ((k6_7 - k5_6) / (k6_7 * k5_6 + 1))
            tan4 = ((K[i][6] - K[i][5]) / (K[i][6] * K[i][5]) + 1)
            if K[i][5] == float('inf') or K[i][5] == float('-inf'):
                cos5 = ((data[i][3] * data[i][17] + data[i][2] * data[i][16]) / \
                       (math.sqrt(data[i][3] * data[i][3] + data[i][2] * data[i][2])
                         * math.sqrt(data[i][16] * data[i][16] + data[i][17] * data[i][17])))
                tan_7 = math.pi - math.acos(cos5)
                theta[i].append(tan_7)
            elif K[i][6] == float('inf') or K[i][6] == float('-inf'):
                cos6 = ((data[i][13] * data[i][15] + data[i][12] * data[i][14]) / \
                       (math.sqrt(data[i][12] * data[i][12] + data[i][13] * data[i][13])
                         * math.sqrt(data[i][14] * data[i][14] + data[i][15] * data[i][15])))
                tan_8 = math.pi - math.acos(cos6)
                theta[i].append(tan_8)
            else:
                theta[i].append(math.atan(tan4))
            # tan5 = ((k1_8 - k1_11) / (k1_8 * k1_11 + 1))
            tan5 = ((K[i][7] - K[i][8]) / (K[i][7] * K[i][8]) + 1)
            if K[i][7] == float('inf') or K[i][7] == float('-inf'):
                cos7 = ((data[i][3] * data[i][17] + data[i][2] * data[i][16]) / \
                       (math.sqrt(data[i][3] * data[i][3] + data[i][2] * data[i][2])
                         * math.sqrt(data[i][16] * data[i][16] + data[i][17] * data[i][17])))
                tan_9 = math.pi - math.acos(cos7)
                theta[i].append(tan_9)
            elif K[i][8] == float('inf') or K[i][8] == float('-inf'):
                cos8 = ((data[i][3] * data[i][23] + data[i][2] * data[i][22]) / \
                       (math.sqrt(data[i][3] * data[i][3] + data[i][2] * data[i][2])
                         * math.sqrt(data[i][22] * data[i][22] + data[i][23] * data[i][23])))
                tan_10 = math.pi - math.acos(cos8)
                theta[i].append(tan_10)
            else:
                theta[i].append(math.atan(tan5))
            # tan6 = ((k0_15 - k0_14) / (k0_15 * k0_14 + 1))
            tan6 = ((K[i][10] - K[i][9]) / (K[i][9] * K[i][10]) + 1)
            if K[i][10] == float('inf') or K[i][10] == float('-inf'):
                cos9 = ((data[i][1] * data[i][33] + data[i][0] * data[i][32]) / \
                       (math.sqrt(data[i][1] * data[i][1] + data[i][0] * data[i][0])
                         * math.sqrt(data[i][32] * data[i][32] + data[i][33] * data[i][33])))
                tan_11 = math.pi - math.acos(cos9)
                theta[i].append(tan_11)
            elif K[i][9] == float('inf') or K[i][9] == float('-inf'):
                cos10 = ((data[i][1] * data[i][29] + data[i][0] * data[i][28]) / \
                        (math.sqrt(data[i][1] * data[i][1] + data[i][0] * data[i][0])
                         * math.sqrt(data[i][28] * data[i][28] + data[i][29] * data[i][29])))
                tan_12 = math.pi - math.acos(cos10)
                theta[i].append(tan_12)
            else:
                theta[i].append(math.atan(tan6))

    return theta

if __name__ == '__main__':
    x_data = np.array(joint_linear_k(data))
    a = np.array(get_joint_theta(x_data, data))
    pi = 2 * math.pi
    a[np.isnan(a)] = pi
    print(a)
    # 把数组中的nan换成2pi,由于tan函数的区间是[-pi/2, pi/2],考虑到关节转动的角度
    # 关节无法转动360度,则将不存在的设置为2pi
    #Y_data = y_data.reshape(44, 1)
    #GBDT

    #x_train, x_test, y_train, y_test = train_test_split(a, Y_data, test_size=0.2)
    #model = GradientBoostingClassifier()
    #model.fit(x_train, y_train)
    #score = model.score(x_test, y_test)
    #print("预测得分为：%s" % score)
    #保存模型
    #joblib.dump(model, 'GBDT.model')
    #lr = joblib.load('GBDT.model')
    #读取模型
    #GBDT2 = joblib.load('save/clf.pkl')
    #print(clf3.predict(X[0:1]))

    #knn算法 精度在0.55-0.77
    '''
    x_train, x_test, y_train, y_test = train_test_split(a, Y_data, test_size=0.2)
    knn = KNeighborsClassifier()
    knn.fit(x_train, y_train)
    score = knn.score(x_test, y_test)
    print("预测得分为：%s" % score)
    '''
    #决策树精度趋于0.88 和 1.0
    '''
    x_train, x_test, y_train, y_test = train_test_split(a, Y_data, test_size=0.2)
    dt = tree.DecisionTreeClassifier()
    dt.fit(x_train, y_train)
    dt.get_params()
    sorce = dt.score(x_test, y_test)
    print("此模型得分为%s" % sorce)
    '''
    # bp神经网络,精度不稳定0.77, 1.0, 0.66, 0.88
    '''
    x_train, x_test, y_train, y_test = train_test_split(a, Y_data, test_size=0.2)
    bp = MLPClassifier(max_iter=1000)
    bp.fit(x_train, y_train)
    bp.get_params()
    sorce = bp.score(x_test, y_test)
    print("此模型得分为%s" % sorce)
    '''
    # 朴素贝叶斯 精度为0.88
    '''
    x_train, x_test, y_train, y_test = train_test_split(a, Y_data, test_size=0.2)
    nb = naive_bayes.GaussianNB()
    nb.fit(x_train, y_train)
    nb.get_params()
    sorce = nb.score(x_test, y_test)
    print("此模型得分为%s" % sorce)
    '''
    #svm, 测试精度0.22
    '''
    clf = svm.SVC(C=2, kernel='rbf', gamma=30, decision_function_shape='ovr')
    clf.fit(x_train, y_train.ravel())
    tra_label=clf.predict(x_train) #训练集的预测标签
    tes_label=clf.predict(x_test) #测试集的预测标签
    print("训练集：", accuracy_score(y_train,tra_label) )
    print("测试集：", accuracy_score(y_test,tes_label) )
    print('decision_function:\n', clf.decision_function(x_train))
    print('\npredict:\n', clf.predict(x_train))
    '''



